import {CmsEditor, PlainCmsNamespace} from "@peryl/react-cms-editor";
import {computed, designComponent, designPage, getComponentCls, iMouseEvent, PropType, useClasses, useModel} from "@peryl/react-compose";
import {$dialog, $previewer, i18n, Icon, Image} from 'plain-design';
import './cms-component-editor.scss';
import {useCmsEditorOption} from "../../../modules/cms-visual-editor";

export const CmsComponentEditor = designComponent({
  name: 'cms-component-editor',
  props: {
    modelValue: { type: [String, Object] as PropType<string | iCmsComponentJsonData> },
    valueTypeString: { type: Boolean },
    disabled: { type: Boolean },
    height: { type: Number, default: 56 },
    previewOnClick: { type: Boolean, default: true },
    useConfig: { type: Object as PropType<PlainCmsNamespace.iUseConfig> }
  },
  emits: {
    onUpdateModelValue: (val?: string | iCmsComponentJsonData) => true,
    onClick: (e: iMouseEvent) => true,
  },
  setup({ props, event: { emit } }) {

    const model = useModel(() => props.modelValue, emit.onUpdateModelValue);

    const jsonData = computed((): iCmsComponentJsonData | null | undefined => {
      const val = model.value;
      if (val == null) {return val;}
      if (typeof val === "string") {
        try {
          const parseData = JSON.parse(val);
          return parseData as iCmsComponentJsonData;
        } catch (e) {
          console.error(e);
          return null;
        }
      } else {
        return val;
      }
    });

    const classes = useClasses(() => [
      getComponentCls('cms-component-editor'),
      {
        'cms-component-editor-disabled': props.disabled,
      }
    ]);

    const handler = {
      onClickImage: (e: iMouseEvent) => {
        const imageUrl = jsonData.value?.image;
        if (!imageUrl) {return;}
        props.previewOnClick && $previewer.preview(imageUrl, e.currentTarget as any);
        emit.onClick(e);
      },
      onClickCover: () => {
        openEditor({
          dataMetas: jsonData.value?.dataMetas,
          useConfig: props.useConfig,
          onSave: (newMetas, image) => {
            console.log({ newMetas, image });
            const newJsonData: null | iCmsComponentJsonData = !newMetas || !image ? null : { dataMetas: newMetas, image };
            if (!newJsonData) {
              model.value = undefined;
            } else {
              model.value = props.valueTypeString ? JSON.stringify(newJsonData) : newJsonData;
            }
          },
        });
      },
    };

    return () => (
      <div className={classes.value}>
        <Image src={jsonData.value?.image} height={props.height} previewOnClick={false} onClick={handler.onClickImage}/>
        <div className="cms-component-editor-cover" onClick={handler.onClickCover}>
          <Icon icon="pi-edit"/>
        </div>
      </div>
    );
  },
});

export interface iCmsComponentJsonData {
  dataMetas: PlainCmsNamespace.iDataMeta[];
  image: string,
}

const openEditor = (
  param: {
    dataMetas?: PlainCmsNamespace.iDataMeta[],
    useConfig?: PlainCmsNamespace.iUseConfig,
    onSave: (newMetas: PlainCmsNamespace.iDataMeta[] | null | undefined, image: string | null | undefined) => void | boolean | Promise<void | boolean>,
    onCancel?: () => void | boolean | Promise<void | boolean>,
  }
) => {
  const close = $dialog({
    position: 'right',
    width: '95%',
    noHead: true,
    noFoot: true,
    noContentPadding: true,
    render: () => (
      <_Editor
        dataMetas={param.dataMetas}
        useConfig={param.useConfig}
        onCancel={async () => {
          const flag = await param.onCancel?.();
          if (flag != false) {close();}
        }}
        onSave={async (newMetas, image) => {
          const flag = await param.onSave?.(newMetas, image);
          if (flag != false) {close();}
        }}
      />
    ),
  });
};

const _Editor = designComponent({
  props: {
    dataMetas: { type: Array as PropType<PlainCmsNamespace.iDataMeta[]> },
    useConfig: { type: Object as PropType<PlainCmsNamespace.iUseConfig> }
  },
  emits: {
    onCancel: () => true,
    onSave: (newDataMetas: PlainCmsNamespace.iDataMeta[] | null | undefined, image: string | undefined) => true,
  },
  setup({ props, event: { emit } }) {

    const option = useCmsEditorOption({
      isRunning: false,
      data: props.dataMetas,
      editorCacheKey: 'DEFAULT_TEMPLATE_EDIT_CACHE',
      ...props.useConfig,
    });

    option.panelOperation.registry(98, 'cancel', 'center', () => (<div className="cms-editor-panel-operation-button" onClick={handler.cancel}><span><Icon icon="pi-close"/></span><span>{i18n.$it('base.cancel').d('取消')}</span></div>));
    option.panelOperation.registry(99, 'save', 'center', () => (<div className="cms-editor-panel-operation-button" onClick={handler.save}><span><Icon icon="pi-save"/></span><span>{i18n.$it('base.edit.save').d('保存')}</span></div>));

    const handler = {
      cancel: () => emit.onCancel(),
      save: async () => {
        const imagePath = await option.methods.getSnapshot();
        emit.onSave(option.state.getStateData(), imagePath);
      },
    };

    return () => (
      <CmsEditor option={option}/>
    );
  }
});
